package com.alumni_circle.core.utils;

import cn.hutool.core.util.StrUtil;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * @author 龙小虬
 * @since 2020-08-01 18:02
 */
public class RsaUtils implements PasswordEncoder {

    public static void main(String[] args) throws Exception {
        System.out.println(decrypt("w7itLkI6Ok8tSBre1ThbI1hglFfHwkx6jBt5ywHFE3Kh6TfzCJ8LNVdWejlWVJ2rXF14H+rz24IzQX2rWQV0ZXZErC8z6lD+siYnwtljZn7e3khqSITJr389pPMkoglUKpNDtm+BwJOC0GC2zHNZAcWBcY6GBLttcVIp4AU2snI="));
    }

    private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXJaJG1x6CPkhwGHuxItQvaaonQDbUsbuWFxaveHFA5bWf6WDlTloeSgiK5gTvN47x5P6IgMHyPacQV2TR/gprhuWmeq1FqwoRd7K0R6gRoxdn0qNvV760NeVHTk6zTJB429hHjyzwmwSduN5vWCvKdfjjQSaHuDOU3cfG1lVuewIDAQAB";
    private static final String PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANclokbXHoI+SHAYe7Ei1C9pqidANtSxu5YXFq94cUDltZ/pYOVOWh5KCIrmBO83jvHk/oiAwfI9pxBXZNH+CmuG5aZ6rUWrChF3srRHqBGjF2fSo29XvrQ15UdOTrNMkHjb2EePLPCbBJ243m9YK8p1+ONBJoe4M5Tdx8bWVW57AgMBAAECgYAvMoFT+xMlTVaEyMoxxMs5j3uVWr/sjwTw2yXN3qUxsHLUntTz2OlqJaGUHvvMIqsII8020tA5PQ8uRY3Hh2xvXTbV3Fuyaj7h75VtIUE84UnN5/9i61amq5XvOzMmyEpoAkjQbTa6CT04r1P+ShAOBbaMlktws30VneWYh5APKQJBAPXgvhFxnNUJe1Aoss8dZDE15K15nz80IqKk0MMnR6zDXHgMKpaCRU20Gq0AVnGOBDHebScHw0C6LGpK302KwncCQQDgAQZXAeHjWgYhI+RmJC6591JJ1sQijlfqGYq7whXlr/Bg3MjxfPA2clzlSYdsTJy6bu2+qr4BGjI/1ApcSJEdAkEAq41ZUBZzFHj/HtimmbeqFmPB3//Bynl3yP8x4VfgvHu6YtAqTsUp0aNeEWLw7V3nM1w70EWsR9cd8jO3RgUQ1QJBAMpdYqLb2nwP6hWqXT5BVc0/N6HpWct2GMouRP0We73C0kBPdWFkY4Zsjqu9X5BhLf3nFPT5Pymzxs2O+8Ue8akCQQC+SbzDmlwG48uS8C6RO6vSEVZEKw3ymomUp3C1Bsj53T6y4qZ9pks3y1Ehz48O/cyC97y4SZajls+r69soR2Ff";


    /**
     * RSA公钥加密
     *
     * @param str 加密字符串
     * @return 密文
     * @throws Exception
     *             加密过程中的异常信息
     */
    private static String encrypt(String str) throws Exception{
        //base64编码的公钥
        byte[] decoded = Base64.decodeBase64(PUBLIC_KEY);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        //RSA加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        return Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
    }


    /**
     * 数据解密
     * @param str
     * @return
     */
    private static String decrypt(String str){
        try {
            if(!StrUtil.hasEmpty(str)) {
                //64位解码加密后的字符串
                byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
                //base64编码的私钥
                byte[] decoded = Base64.decodeBase64(PRIVATE_KEY);
                RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
                //RSA解密
                Cipher cipher = Cipher.getInstance("RSA");
                cipher.init(Cipher.DECRYPT_MODE, priKey);
                return new String(cipher.doFinal(inputByte));
            }
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
        return "fail";
    }

    /**
     * 数据比较
     * @param encode
     * @param decrypt
     * @return
     */
    public static boolean matches(String decrypt,String encode){
        return decrypt(decrypt).equals(encode);

    }


    /**
     * 加密
     * @param charSequence 原密码
     * @return
     */
    @Override
    public String encode(CharSequence charSequence) {
        try {
            return encrypt(charSequence.toString());
        } catch (Exception e) {

        }
        return null;
    }

    /**
     *
     * @param charSequence 前端传输的密码
     * @param s 数据库内的密码
     * @return
     */
    @Override
    public boolean matches(CharSequence charSequence, String s) {
        return matches(s,charSequence.toString());
    }
}
